﻿// --- Copyright (c) 2010 Steven Hartgers ---
// Copyright (C) 2010 Steven Hartgers All rights are reserved.
// Author contact: fiinix00/at\gmail.com
// ------------------------------------------------------------------------
// This program is free software: you can redistribute it and/or modify 
// it under the terms of the GNU General Public License as published by 
// the Free Software Foundation, either version 3 of the License, or 
// (at your option) any later version. 
//  
// This program is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
// GNU General Public License for more detail
//  
// You should have received a copy of the GNU General Public License 
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
// ------------------------------------------------------------------------
// COPYRIGHT NOTICE: This copyright notice may NOT be removed, obscured or modified 
// without written consent from the author.
// --- End copyright notice --- 


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
using System.ComponentModel;
using System.Reflection;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Hack.Conversion;
using System.Collections.Specialized;
using System.Net.Mime;
using System.IO.Compression;
using System.Security.Cryptography;
using System.Web;
using System.Runtime.InteropServices;
using Hack.SystemAPI;
using Microsoft.Win32;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using Hack.Attributes;
using NetFx.AGIL;
using NetFx.SMIL;
using System.Drawing.Imaging;
using SMath = System.Math;
using SConsole = System.Console;
using System.Globalization;
using Hack.DataStructures;
using System.Collections.ObjectModel;
using System.Data;
using Hack.Reflection;
using System.Linq.Expressions;
using Hack.Synchronization;

namespace Hack.Extensions
{
    [Extension]
    public static class ClassExtensions
    {
        public delegate void Inspector();
        public delegate void InspectorMethodinfo(MethodInfo a);
        public delegate void InspectorInt(int a);
        public delegate void InspectorStr(string a);
        public delegate void InspectorStrA(string[] a);
        public delegate void InspectorBool(bool a);
        public delegate void InspectorChar(char a);
        public delegate void InspectorByte(byte a);
        public delegate void InspectorByteA(byte[] a);
        public delegate void InspectorEnum(Enum a);
        public delegate void InspectorObj(object a);
        public delegate void InspectorMethodbase(MethodBase a);

        public delegate void InspectorFuncArg1<T>(Func<T> f);
        public delegate void InspectorFuncArg2<TA, TB>(Func<TA, TB> f);
        public delegate void InspectorFuncArg3<TA, TB, TC>(Func<TA, TB, TC> f);
        public delegate void InspectorFuncArg4<TA, TB, TC, TD>(Func<TA, TB, TC, TD> f);

        public delegate T InspectorReturn<T>();
        public delegate T InspectorMethodinfoReturn<T>(MethodInfo a);
        public delegate T InspectorIntReturn<T>(int a);
        public delegate T InspectorStrReturn<T>(string a);
        public delegate T InspectorStrAReturn<T>(string[] a);
        public delegate T InspectorBoolReturn<T>(bool a);
        public delegate T InspectorCharReturn<T>(char a);
        public delegate T InspectorByteReturn<T>(byte a);
        public delegate T InspectorByteAReturn<T>(byte[] a);
        public delegate T InspectorEnumReturn<T>(Enum a);
        public delegate T InspectorObjReturn<T>(object a);
        public delegate T InspectorMethodbaseReturn<T>(MethodBase a);

        public static void Inspect(this MethodBase method)
        {
            if (method != null)
            {
                var agils = new List<AgilOperation>();

                using (AgilGeneratorReader reader = AgilGeneratorReader.of(method))
                {
                    if (reader.SymanticParse(agils))
                    {
                        foreach (AgilOperation agil in agils)
                        {
                            if (agil != null)
                            {
                                System.Console.WriteLine(agil.ToString());
                            }
                        }
                    }
                }


                var smils = new List<SmilOperation>();

                using (SmilCodeAnalyser ca = SmilCodeAnalyser.of(method))
                {
                    if (ca.Parse(smils))
                    {
                        foreach (SmilOperation smil in smils)
                        {
                            if (smil != null)
                            {
                                System.Console.WriteLine(smil.ToString());
                            }
                        }
                    }
                }
            }
        }

        public static void Inspect(this Action a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }

        }
        public static void Inspect<T>(this Action<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }

        }
        public static void Inspect<TA, TB>(this Action<TA, TB> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }

        }
        public static void Inspect<TA, TB, TC>(this Action<TA, TB, TC> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }

        }
        public static void Inspect<TA, TB, TC, TD>(this Action<TA, TB, TC, TD> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }

        }


        public static void Inspect(this Inspector a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect(this InspectorBool a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect(this InspectorMethodinfo a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect(this InspectorMethodbase a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }

        public static void Inspect(this InspectorByte a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect(this InspectorByteA a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect(this InspectorChar a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect(this InspectorEnum a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect(this InspectorInt a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect(this InspectorObj a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect(this InspectorStr a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect(this InspectorStrA a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }

        public static void Inspect<T>(this InspectorReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect<T>(this InspectorBoolReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect<T>(this InspectorMethodinfoReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect<T>(this InspectorMethodbaseReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }

        public static void Inspect<T>(this InspectorByteReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect<T>(this InspectorByteAReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect<T>(this InspectorCharReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect<T>(this InspectorEnumReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect<T>(this InspectorIntReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect<T>(this InspectorObjReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect<T>(this InspectorStrReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect<T>(this InspectorStrAReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }

        public static void Inspect(this Delegate a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect(this Delegate a, Object[] o)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }

        public static void Inspect<T>(this Func<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect<TA, TB>(this Func<TA, TB> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect<TA, TB, TC>(this Func<TA, TB, TC> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect<TA, TB, TC, TD>(this Func<TA, TB, TC, TD> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect<TA, TB, TC, TD, TE>(this Func<TA, TB, TC, TD, TE> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }

        public static void Inspect<T>(this InspectorFuncArg1<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect<TA, TB>(this InspectorFuncArg2<TA, TB> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect<TA, TB, TC>(this InspectorFuncArg3<TA, TB, TC> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void Inspect<TA, TB, TC, TD>(this InspectorFuncArg4<TA, TB, TC, TD> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                Inspect(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }







        public static void InspectILBytes(this MethodBase method)
        {
            if (method != null)
            {
                method.GetMethodBody()
                    .GetILAsByteArray()
                        .ForEach((_byte) =>
                        {
                            SConsole.Write("{0:X} ", _byte);
                        });
            }
        }

        public static void InspectILBytes(this Action a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }

        }
        public static void InspectILBytes<T>(this Action<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }

        }
        public static void InspectILBytes<TA, TB>(this Action<TA, TB> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }

        }
        public static void InspectILBytes<TA, TB, TC>(this Action<TA, TB, TC> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }

        }
        public static void InspectILBytes<TA, TB, TC, TD>(this Action<TA, TB, TC, TD> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }

        }


        public static void InspectILBytes(this Inspector a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes(this InspectorBool a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes(this InspectorMethodinfo a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes(this InspectorMethodbase a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }

        public static void InspectILBytes(this InspectorByte a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes(this InspectorByteA a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes(this InspectorChar a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes(this InspectorEnum a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes(this InspectorInt a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes(this InspectorObj a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes(this InspectorStr a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes(this InspectorStrA a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }

        public static void InspectILBytes<T>(this InspectorReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes<T>(this InspectorBoolReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes<T>(this InspectorMethodinfoReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes<T>(this InspectorMethodbaseReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }

        public static void InspectILBytes<T>(this InspectorByteReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes<T>(this InspectorByteAReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes<T>(this InspectorCharReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes<T>(this InspectorEnumReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes<T>(this InspectorIntReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes<T>(this InspectorObjReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes<T>(this InspectorStrReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes<T>(this InspectorStrAReturn<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }

        public static void InspectILBytes(this Delegate a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes(this Delegate a, Object[] o)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }

        public static void InspectILBytes<T>(this Func<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes<TA, TB>(this Func<TA, TB> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes<TA, TB, TC>(this Func<TA, TB, TC> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes<TA, TB, TC, TD>(this Func<TA, TB, TC, TD> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes<TA, TB, TC, TD, TE>(this Func<TA, TB, TC, TD, TE> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }

        public static void InspectILBytes<T>(this InspectorFuncArg1<T> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes<TA, TB>(this InspectorFuncArg2<TA, TB> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes<TA, TB, TC>(this InspectorFuncArg3<TA, TB, TC> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
        public static void InspectILBytes<TA, TB, TC, TD>(this InspectorFuncArg4<TA, TB, TC, TD> a)
        {
            Type t = a.GetType();
            if (t != null)
            {
                InspectILBytes(MethodBase.GetMethodFromHandle(a.Method.MethodHandle));
            }
        }
    }
}
